package prodapi

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"sync/atomic"

	"io/ioutil"

	"git.oschina.net/antlinker/antevent/server/antoauth"
	"git.oschina.net/antlinker/antevent/server/app"
	"git.oschina.net/antlinker/antevent/server/client"
)

// Options 客户端配置
type Options struct {
	Host    string
	Name    string
	Scheme  string
	AuthCfg antoauth.SignerOption
}

// NewClient 创建新的客户端
func NewClient(opt Options) Clienter {
	c := client.New(nil)
	c.Host = opt.Host
	c.Scheme = opt.Scheme
	c.SetAntoAuthSigner(antoauth.NewSigner(opt.AuthCfg))

	return defaultCli{
		name: opt.Name,
		cli:  c,
	}

}

const (
	eidFormat = "%s-%s-%s-%d-%d"
)

var (
	seq int64
)

// Clienter 事件生产者客户端
type Clienter interface {
	Send(ctx context.Context, etype, action string, params interface{}) (eid string, err error)
}
type defaultCli struct {
	name string
	cli  *client.Client
}

func (c defaultCli) Send(ctx context.Context, etype, action string, params interface{}) (eid string, err error) {
	n := time.Now()
	p := &client.PutEventPayload{

		Etype:   etype,
		Action:  action,
		From:    c.name,
		Occtime: &n,
		Params:  &params,
	}
	eid = c.createEid(etype, action)
	resp, err := c.cli.PutEvent(ctx, client.PutEventPath(eid), p)
	if err != nil {
		return
	}
	if resp.StatusCode <= 200 || resp.StatusCode > 300 {
		data, err1 := ioutil.ReadAll(resp.Body)
		if err1 != nil {
			err = err1
			return
		}
		if data != nil {
			var m app.AntError
			err1 := json.Unmarshal(data, &m)
			if err1 != nil {
				err = err1
				return
			}
			if m.Msg != nil {
				err = errors.New(*m.Msg)
			}
			return
		}
		return
	}
	return "", nil
}

func (c defaultCli) createEid(etype, action string) string {
	ind := atomic.AddInt64(&seq, 1)
	return fmt.Sprintf(eidFormat, c.name, etype, action, time.Now().Unix(), ind)
}
